package com.example.demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author adr
 */
public class ConnectTask implements Runnable {
    String localIp;
    private ADBPortRegister register;
    private Socket accept;
    ThreadPoolExecutor executor;
    private final static String REGSITER = "register";
    private final static String HB = "hb";
    private final static String UNREGSITER = "un_register";
    InputStream inputStream = null;
    OutputStream outputStream = null;
    boolean die = false;

    public ConnectTask(ADBPortRegister register, Socket socket, ThreadPoolExecutor executor) {
        this.register = register;
        this.accept = socket;
        this.executor = executor;
        try {
            inputStream = accept.getInputStream();
            outputStream = accept.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            boolean callUnregister = false;
            String type = ReadHelper.read(inputStream);
            localIp = ReadHelper.read(inputStream);
            String emName = AdbManager.findMatchDeviceName(localIp);
            int port = AdbManager.register(emName);
            register.map.put(emName, port);
            if (!register.freePort.contains(port - 1)) {
                register.freePort.add(port - 1);
            }
            WriteHelper.sendData(outputStream, "ok");
            WriteHelper.sendData(outputStream, "" + port);
            executor.execute(hbTask);
            Thread.currentThread().interrupt();
            while (!accept.isClosed() && !accept.isInputShutdown()) {
                type = ReadHelper.read(inputStream);
                if (UNREGSITER.equals(type)) {
                    callUnregister = true;
                    System.out.println(localIp + " disconnect by unregister.");
                    executor.remove(hbTask);
                    die = true;
                    register.disconnect(localIp);
                    WriteHelper.sendData(outputStream, "connect_block_ok");
                    break;
                } else if (HB.equals(type)) {
                    String content = ReadHelper.read(inputStream);
//                    System.out.println(localIp + " handle heart beat msg:" + content);
                }
            }
            if (!callUnregister) {
                System.out.println(localIp + " disconnect by read error.");
                die = true;
                executor.remove(hbTask);
                register.disconnect(localIp);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(localIp + " disconnect by read io exception.");
            executor.remove(hbTask);
            die = true;
            register.disconnect(localIp);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                accept.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    Runnable hbTask = () -> {
        while (!accept.isClosed() && !accept.isOutputShutdown() && accept.isConnected() && !die) {
            try {
                Thread.sleep(5000);
                try {
                    WriteHelper.sendData(outputStream, HB);
                } catch (IOException e) {
                    System.out.println(localIp + " disconnect by heart beat stop.");
                    register.disconnect(localIp);
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
}
